package com.nchu.student_score.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.nchu.student_score.dataObject.TeachTaskResult;
import com.nchu.student_score.mapper.*;
import com.nchu.student_score.model.*;
import com.nchu.student_score.service.TeachService;
import com.nchu.student_score.util.Define;
import com.nchu.student_score.vo.ResultVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.util.*;

@Service
public class TeachServiceImpl implements TeachService {
    @Autowired
    TeachTaskMapper taskMapper;
    @Autowired
    TeachClazzMapper clazzMapper;
    @Autowired
    TeachPersonalMapper personalMapper;
    @Autowired
    StudentMapper studentMapper;
    @Autowired
    GradeTempMapper gradeTempMapper;
    @Autowired
    GradeMapper gradeMapper;

    @Override
    public ResultVo<TeachTask> confirmTeachTask(TeachTaskResult input) {//教师确认教学安排
        ResultVo<TeachTask> resultVo = new ResultVo<>();
        if(input.getTeachId() == null || input.getTeachState() != 0){
            resultVo.setStatus(1);
            resultVo.setMessage("当前课程安排状态无法更改!");
            return resultVo;
        }
        else{
            input.setTeachState(1);
        }

        //准备空的成绩缓存表数据
        String teachId = input.getTeachId();//获得主键
        List<String> taskIds = new ArrayList<>();//查询需要taskId集合
        taskIds.add(teachId);//teachId有且仅有一个
        List<TeachClazz> clazzes = clazzMapper.selectAllByTaskIds(taskIds);//查出所有被选中的"班级"
        List<Student> students = personalMapper.selectAllByTaskIds(taskIds);//查出所有被选中的"个人"
        List<Student> students1 = studentMapper.selectByClazz(clazzes);//通过被选中的班级查出学生

        List<GradeTemp> gradeTempList = new ArrayList<>();
        for(Student s:students){
            s.setClazzId(null);//直接添加的学生个人不需要班级
            gradeTempAddStudent(gradeTempList,s,teachId);
        }
        for(Student s:students1){
            gradeTempAddStudent(gradeTempList,s,teachId);
        }

        if(gradeTempList.size() > 0)//数量不为0则插入成绩缓存表
            gradeTempMapper.insertAll(gradeTempList);

        taskMapper.updateByPrimaryKey(taskChange1(input));//更新教学安排
        resultVo.setMessage("确认课程安排成功!");
        resultVo.setStatus(0);
        return resultVo;
    }

    //成绩缓存集合添加数据
    private void gradeTempAddStudent(List<GradeTemp> gradeTempList,Student student,String teachId){
        GradeTemp gradeTemp = new GradeTemp();
        gradeTemp.setTeachId(teachId);
        gradeTemp.setStuId(student.getStuId());
        if(student.getClazzId() != null)
            gradeTemp.setClazzId(student.getClazzId());
        gradeTempList.add(gradeTemp);
    }

    @Override
    public PageInfo<TeachTaskResult> getTeachTaskList(TeachTask input, Integer currPage) {
        if(currPage == null) currPage = 1;
        PageHelper.startPage(currPage, Define.PAGE_SIZE);
        PageInfo<TeachTaskResult> pageInfo = new PageInfo<>(taskMapper.findTeachTasks(input));//分页查询

        List<TeachTaskResult> list =  pageInfo.getList();//取出分页查询的结果 - 教学安排
        if(list == null || list.size() == 0)//集合为空直接返回
            return pageInfo;

        Map<String,TeachTaskResult> map = new HashMap<>();
        for(TeachTaskResult t:list){
            map.put(t.getTeachId(),t);//以teachId为key将教学安排存入hashmap
        }

        List<String> taskIds = new ArrayList<>();//查询需要taskId集合
        for(TeachTaskResult t:list){
            taskIds.add(t.getTeachId());
        }

        List<Student> students = personalMapper.selectAllByTaskIds(taskIds);//查出所有被选中的"个人"
        for(Student s:students){
            TeachTaskResult t = map.get(s.getStuIdCard());//用stuIdCard充当teachId，将教学安排取出
            if(t.getStudents() == null)
               t.setStudents(new ArrayList<>());//避免空指针异常
            t.getStudents().add(s);
        }

        List<TeachClazz> clazzes = clazzMapper.selectAllByTaskIds(taskIds);//查出所有被选中的"班级"
        for(TeachClazz c:clazzes){
            TeachTaskResult t = map.get(c.getTeachId());//将教学安排取出
            if(t.getClazzes() == null)
                t.setClazzes(new ArrayList<>());//避免空指针异常
            Clazz clazz = new Clazz();
            clazz.setClazzId(c.getClazzId());
            t.getClazzes().add(clazz);
        }

        for(TeachTaskResult tk : list){//计算总人数、通过人数、通过率
            if(tk.getTeachState() == 2){//已完成的课程安排
                //查出该安排下所有成绩 用于计算排名和比例 已隐藏学生学号
                List<Grade> gradeList = gradeMapper.selectByTeachId(tk.getTeachId());
                int passCount = 0;//合格人数
                int total = gradeList.size();//总人数
                double passPct;//合格率
                for(Grade g : gradeList){//遍历获得通过人数
                    if(g.getScore() >= tk.getPassingScore())
                        passCount++;
                }
                passPct = passCount * 100.0 / total;//计算通过率
                tk.setPass(passCount);
                tk.setTotal(total);
                tk.setPassPct(Double.valueOf(new DecimalFormat("#.00").format(passPct)));//保留2位小数
            }
        }

        pageInfo.setList(list);//将处理后的查询结果重新set并返回
        return pageInfo;
    }

    @Override
    public ResultVo<TeachTask> insertTeachTask(TeachTaskResult input) {
        ResultVo<TeachTask> resultVo = new ResultVo<>();

        if(input.getTeachId() == null || input.getTeachId().equals("-1")){//插入
            TeachTask task = taskChange1(input);    //转换类型
            taskMapper.insert(task);                //插入
            String teachId = task.getTeachId();     //返回的自增主键

            List<Integer> clazz = input.getClazz();
            updateClazzes(clazz,teachId,"insert");//插入班级
            List<Integer> student = input.getStudent();
            updateStudents(student,teachId,"insert");//插入学生

            resultVo.setStatus(0);
            resultVo.setMessage("新增课程安排成功!");
        }
        else{//修改教学安排
            String teachId = input.getTeachId();//获得主键

            TeachTask task = taskMapper.selectByPrimaryKey(teachId);
            if(task == null || task.getTeachState() != 0){
                resultVo.setStatus(1);
                resultVo.setMessage("当前课程安排已确认，无法修改!");
                return resultVo;
            }

            List<Integer> clazzNew = input.getClazz();//新的班级列表
            List<Integer> studentNew = input.getStudent();//新的学生列表

            List<String> taskIds = new ArrayList<>();//查询需要taskId集合
            taskIds.add(teachId);//teachId有且仅有一个
            List<TeachClazz> clazzes = clazzMapper.selectAllByTaskIds(taskIds);//查出所有被选中的"班级"
            List<Student> students = personalMapper.selectAllByTaskIds(taskIds);//查出所有被选中的"个人"
            List<Integer> clazzOld = new ArrayList<>();//原有的班级列表
            List<Integer> studentOld = new ArrayList<>();//原有的学生列表
            for(TeachClazz c:clazzes){
                clazzOld.add(c.getClazzId());
            }
            for(Student s:students){
                studentOld.add(s.getStuId());
            }

            IntegerListRemoveSame(clazzOld,clazzNew);//清除两个集合中相同数据
            IntegerListRemoveSame(studentOld,studentNew);//清除两个集合中相同数据

            updateClazzes(clazzNew,teachId,"insert");//插入新班级
            updateClazzes(clazzOld,teachId,"delete");//删除原班级
            updateStudents(studentNew,teachId,"insert");//插入新学生
            updateStudents(studentOld,teachId,"delete");//删除原学生

            taskMapper.updateByPrimaryKey(taskChange1(input));//更新教学安排
            resultVo.setStatus(0);
            resultVo.setMessage("更改课程安排成功!");
        }
        return resultVo;
    }

    private void updateStudents(List<Integer> student,String teachId,String operation){//更新学生
        if(student != null && student.size() > 0){ //选中的学生数量不为0则插入
            TeachPersonal[] teachPersonals = new TeachPersonal[student.size()];
            for(int i = 0;i < student.size();i++){
                teachPersonals[i] = new TeachPersonal();
                teachPersonals[i].setTeachId(teachId);
                teachPersonals[i].setStuId(student.get(i));
            }
            if(operation.equals("insert"))
                personalMapper.insertAll(teachPersonals);
            else if(operation.equals("delete"))
                personalMapper.deleteAll(teachPersonals);
        }
    }

    private void updateClazzes(List<Integer> clazz,String teachId,String operation){//更新班级
        if(clazz != null && clazz.size() > 0){ //选中的班级数量不为0则插入
            TeachClazz[] clazzes = new TeachClazz[clazz.size()];
            for(int i = 0;i < clazz.size();i++){
                clazzes[i] = new TeachClazz();
                clazzes[i].setTeachId(teachId);
                clazzes[i].setClazzId(clazz.get(i));
            }
            if(operation.equals("insert"))
                clazzMapper.insertAll(clazzes);
            else if(operation.equals("delete"))
                clazzMapper.deleteAll(clazzes);
        }
    }

    private void IntegerListRemoveSame(List<Integer> oldList,List<Integer> newList){//删除二者相同的数据
        if(oldList == null || newList == null || oldList.size() == 0 || newList.size() == 0){
            return ;//其中一个list没有数据则没有必要操作
        }
        for(int i = 0;i < oldList.size();){
            boolean check = true;
            for(int j = 0;j < newList.size();){
                if(Objects.equals(oldList.get(i), newList.get(j))){
                    oldList.remove(i);
                    newList.remove(j);
                    check = false;
                    break;
                }
                else
                    j++;
            }
            if(check)
                i++;
        }
    }

    private TeachTask taskChange1(TeachTaskResult input){//将输入的TeachTask转换为数据库操作需要的类型
        TeachTask task = new TeachTask();

        if(input.getTeachId() != null && (! input.getTeachId().equals("-1"))){
            task.setTeachId(input.getTeachId());
        }
        task.setTeachName(input.getTeachName());
        task.setCourseId(input.getCourseId());
        task.setTeacherId(input.getTeacherId());
        task.setTermId(input.getTermId());
        task.setMethod(input.getMethod());
        task.setFullScore(input.getFullScore());
        task.setPassingScore(input.getPassingScore());
        task.setUsualPct(input.getUsualPct());
        task.setExpPct(input.getExpPct());
        task.setMidPct(input.getMidPct());
        task.setFinalPct(input.getFinalPct());
        task.setOtherPct(input.getOtherPct());
        task.setTeachState(input.getTeachState());
        return task;
    }
}
